#include "../include/json.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#include "../include/AllInOne.hpp"
#include "../include/classfactory.hpp"

using namespace std;
using json = nlohmann::json;

json openfile()
{
    ifstream file("./json/input1.json");
    if (!file.is_open())
        cerr << "Failed to open file" << endl;
    json j;
    file >> j;
    file.close();
    return j;
}
void registerAllTypes(int n_, int p_, double T_, vector<double> value_) {
    TimeIntergratorFactory::createFactory().registerProduct("AdamsBashforth", createAdamsBashforth);
    TimeIntergratorFactory::createFactory().registerProduct("AdamsMoulton", createAdamsMoulton);
    TimeIntergratorFactory::createFactory().registerProduct("BackDifferFormula", createBackDifferFormula);
    TimeIntergratorFactory::createFactory().registerProduct("ClassicalRK", createClassicalRK);
    TimeIntergratorFactory::createFactory().registerProduct("DormandPrinceEmbededRK", createDormand);
    TimeIntergratorFactory::createFactory().registerProduct("ESDIRK", createESDIRK);
    TimeIntergratorFactory::createFactory().registerProduct("FehlbergEmbededRK", createFehlberg);
    TimeIntergratorFactory::createFactory().registerProduct("GaussLegendRK", createGaussLegend);
}

int main()
{
    json input = openfile();
    int dim = input["InitialValue"].size();
    double T = input["Time"];
    int p = input["p"];
    int n_steps = input["n_size"];
    vector<double> value;
    for (int i = 0; i < dim; i++)
        value.push_back(input["InitialValue"][i]);
        
    registerAllTypes(n_steps, p, T, value);
    auto obj = TimeIntergratorFactory::createFactory().create("AdamsBashforth", n_steps, p, T, value);
    obj->solver();
    obj->error();
    return 0;
}